import logging
import tsl_backend.common as common
# import tsl_backend.frontend_api.models.route as routes
import tsl_backend.frontend_api.models.order_routing as order_routing
import tsl_backend.frontend_api.models.workorder as workorders

def get_routing_history(order_route_detail_obj):
    routingHistory_list=[]

    flow=order_route_detail_obj.flow
    workCount=order_route_detail_obj.seq #生产次数

    # get the latest record of this flow
    lastest_order_route_records=order_route_detail_obj.record_set.order_by("pk")
    # lastest_order_route_record=order_route_detail_obj.record_set.order_by("pk").last()
    
    if lastest_order_route_records.exists():
        logging.info(f"Order records exist: {lastest_order_route_records}")
        for lastest_order_route_record in lastest_order_route_records:
            startDate=None
            workerName=None
            worker_duration=None
            qcName=None
            qc_endDate=None
            leaderName=None
            leader_endDate=None
            stoneCheckName=None
            stoneCheck_endDate=None
            dispatchName=None
            qc_check_pk=None
            leader_check_pk=None
            stone_check_pk=None

            dispatcher=lastest_order_route_record.route_detail.dispatcher
            logging.info(f"Dispatcher for {lastest_order_route_record}: {dispatcher}")
            if dispatcher:

                dispatchName=dispatcher.centersender if dispatcher.centersender else None
                dispatch_end_at=dispatcher.formatted_end_at()
            else:
                dispatch_end_at=None
            
            if flow.chinese_name=='PF':
                dispatch_end_at=order_route_detail_obj.order_route.formatted_order_complete_date()
        
            if flow.scan_and_record:
                scan_and_record=True
                if lastest_order_route_record:
                    if lastest_order_route_record.worker:
                        # get latest record
                        if lastest_order_route_record.worker:
                            # workCount=lastest_order_route_record.worker.work_count
                            startDate=lastest_order_route_record.worker.workeractionrecord_set.all().order_by('pk').first().formatted_time() if lastest_order_route_record.worker.workeractionrecord_set.all().order_by('pk').first() else None
                            workerName=lastest_order_route_record.worker.account.django_user.cnName if lastest_order_route_record.worker.account else None
                            worker_duration=lastest_order_route_record.worker.get_work_duration_in_hour()
                        else:
                            # workCount=0
                            startDate=None
                            workerName=None
                            worker_duration=None

            else:
                startDate='noconfig'
                workerName='noconfig'
                worker_duration='noconfig'
                scan_and_record=False

            if flow.qc_check:
                qc_check=True
                if lastest_order_route_record:
                    if lastest_order_route_record.qc_check:
                        qc_check_pk=lastest_order_route_record.qc_check.pk
                        qcName=lastest_order_route_record.qc_check.account.django_user.cnName if lastest_order_route_record.qc_check.account else None
                        qc_endDate=lastest_order_route_record.qc_check.formatted_check_at()

            else:
                qc_check_pk='noconfig'
                qcName='noconfig'
                qc_endDate='noconfig'
                qc_check=False

            
            if flow.leader_check:
                leader_check=True
                if lastest_order_route_record:
                    if lastest_order_route_record.leader_check:
                        leader_check_pk=lastest_order_route_record.leader_check.pk
                        leaderName=lastest_order_route_record.leader_check.account.django_user.cnName if lastest_order_route_record.leader_check.account else None
                        leader_endDate=lastest_order_route_record.leader_check.formatted_check_at()
            else:
                leader_check=False
                leader_check_pk='noconfig'
                leaderName='noconfig'
                leader_endDate='noconfig'

            if flow.stone_exam:
                stone_exam=True
                if lastest_order_route_record:
                    if lastest_order_route_record.stone_check:
                        stone_check_pk=lastest_order_route_record.stone_check.pk
                        stoneCheckName=lastest_order_route_record.stone_check.account.django_user.cnName if lastest_order_route_record.stone_check.account else None
                        stoneCheck_endDate=lastest_order_route_record.stone_check.formatted_check_at()
            else:
                stone_exam=False
                stone_check_pk='noconfig'
                stoneCheckName='noconfig'
                stoneCheck_endDate='noconfig'

            routingHistory={
                    "workCount": workCount,
                    "flow": flow.chinese_name,
                    "startDate": startDate,  
                    "workerName": workerName,  
                    "worker_duration": worker_duration,  
                    "qcName": qcName,  
                    "qc_endDate": qc_endDate,
                    "leaderName": leaderName,  
                    "leader_endDate": leader_endDate,
                    "stoneCheckName": stoneCheckName,  
                    "stoneCheck_endDate": stoneCheck_endDate,
                    "dispatchName": dispatchName,
                    "dispatchName_endDate": dispatch_end_at,
                    "qc_check_pk":qc_check_pk,
                    "leader_check_pk":leader_check_pk,
                    "stone_check_pk":stone_check_pk
                }
            
            routingHistory_list.append(routingHistory)
        
    else:
        routingHistory=routingHistory={
                    "workCount": workCount,
                    "flow": flow.chinese_name,
                    "startDate": None,  
                    "workerName": None,  
                    "worker_duration": None,  
                    "qcName": None,  
                    "qc_endDate": None,
                    "leaderName": None,  
                    "leader_endDate": None,
                    "stoneCheckName": None,  
                    "stoneCheck_endDate": None,
                    "dispatchName": None,
                    "qc_check_pk":None,
                    "leader_check_pk":None,
                    "stone_check_pk":None
                }
        routingHistory_list.append(routingHistory)
            
    return routingHistory_list

def parse_orderonhold_data(on_hold_record_objs):
    
    if on_hold_record_objs.exists():
        data = [{
                    # "route_detail": record.route_detail_id,
                    "orderNo": record.route_detail.order_route.workorder.order,
                    "worker": {
                        "actionRecord": [{
                            "action": action_record.get_action_display(),
                            "time": action_record.formatted_time()
                        } for action_record in record.worker.workeractionrecord_set.all()],
                        # "cnName": record.worker.account.django_user.cnName if record.worker.account else None if record.worker else None
                        "cnName": record.worker.account.django_user.cnName if record.worker and record.worker.account and record.worker.account.django_user else None 
                    },
                    "qcCheck": {
                        "check_record_pk":record.qc_check.pk if record.qc_check else None,
                        "failed": record.qc_check.failed if record.qc_check else None,
                        "remark": record.qc_check.remark if record.qc_check else None,
                        "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record.qc_check.failed_details.all() ] if record.qc_check else [],
                        "rec_time": record.qc_check.formatted_received_at() if record.qc_check else None,
                        "check_time": record.qc_check.formatted_check_at() if record.qc_check else None,
                        # "cnName": record.qc_check.account.django_user.cnName if record.qc_check.account else None if record.qc_check else None
                        "cnName": record.qc_check.account.django_user.cnName if record.qc_check and record.qc_check.account and record.qc_check.account.django_user else None 
                    },
                    "leaderCheck": {
                        "check_record_pk":record.leader_check.pk if record.leader_check else None,
                        "failed": record.leader_check.failed if record.leader_check else None,
                        "remark": record.leader_check.remark if record.leader_check else None,
                        "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record.leader_check.failed_details.all() ] if record.leader_check else [],
                        "rec_time": record.leader_check.formatted_received_at() if record.leader_check else None,
                        "check_time": record.leader_check.formatted_check_at() if record.leader_check else None,
                        # "cnName": record.leader_check.account.django_user.cnName if record.leader_check.account else None if record.leader_check else None
                        "cnName": record.leader_check.account.django_user.cnName if record.leader_check and record.leader_check.account and record.leader_check.account.django_user else None 
                    },
                    "stoneCheck": {
                        "check_record_pk":record.stone_check.pk if record.stone_check else None,
                        "failed": record.stone_check.failed if record.stone_check else None,
                        "remark": record.stone_check.remark if record.stone_check else None,
                        "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record.stone_check.failed_details.all() ] if record.stone_check else [],
                        "rec_time": record.stone_check.formatted_received_at() if record.stone_check else None,
                        "check_time": record.stone_check.formatted_check_at() if record.stone_check else None,
                        # "cnName": record.stone_check.account.django_user.cnName if record.stone_check else None if record.stone_check.account else None if record.stone_check.account.django_user else None
                        "cnName": record.stone_check.account.django_user.cnName if record.stone_check and record.stone_check.account and record.stone_check.account.django_user else None 
                    }
                } for record in on_hold_record_objs]
        
        # print(data)
        
        grouped_data = {}
        for record in data:
            order_no = record["orderNo"]
            if order_no in grouped_data:
                # check if the worker start
                if record["worker"]["cnName"]:
                    grouped_data[order_no]["record"].append({"worker": record["worker"], "qcCheck": record["qcCheck"], "leaderCheck": record["leaderCheck"], "stoneCheck": record["stoneCheck"]})
                else:
                    logging.info(f"This record is rework flow. The worker has not started the flow yet. Keep the last record and no need to show this record. worker: {record['worker']}")
            else:
                grouped_data[order_no] = {"orderNo": order_no, "record": [{"worker": record["worker"], "qcCheck": record["qcCheck"], "leaderCheck": record["leaderCheck"], "stoneCheck": record["stoneCheck"]}]}
        
        result = [{"orderNo": record["orderNo"], "history": record["record"]} for record in grouped_data.values()]

    else:
        logging.info(f"No record")
        result=[]

    return result

def parse_orderview_data_bak_2(detail_obj, user_account_obj):

    data={}

    last_record_obj_by_role=common.get_latest_order_flow_record_by_role(detail_obj, user_account_obj)
    last_record_obj = common.get_last_order_flow_record(detail_obj)

    logging.info(f"{last_record_obj_by_role=}")
    logging.info(f"{last_record_obj=}")
    fail_restart_flow = True if last_record_obj_by_role!=last_record_obj else False

    logging.info(f"{fail_restart_flow=}")

    if last_record_obj_by_role:
        if user_account_obj.role.name=="WORKER":
            if last_record_obj_by_role.worker:
                # check permission
                data={"worker": {
                            "actionRecord": [{
                                "action": action_record_obj.get_action_display(),
                                "time": action_record_obj.formatted_time()
                            } for action_record_obj in last_record_obj_by_role.worker.workeractionrecord_set.all()],
                            "cnName": last_record_obj_by_role.worker.account.django_user.cnName if last_record_obj_by_role.worker.account else ''
                        }}
            else:
                data={"worker": {
                            "actionRecord": [],
                            "cnName": ''
                        }}
        elif user_account_obj.role.name=="QC":
            if last_record_obj_by_role.qc_check:
                if fail_restart_flow:
                    allow_reset = common.check_allow_qc_reset(last_record_obj_by_role, user_account_obj, last_record_obj)
                    if allow_reset:
                        data={"qcCheck": {
                                    "check_record_obj_pk":last_record_obj_by_role.qc_check.pk if last_record_obj_by_role.qc_check else '',
                                    "failed": last_record_obj_by_role.qc_check.failed,
                                    "remark": last_record_obj_by_role.qc_check.remark,
                                    "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in last_record_obj_by_role.qc_check.failed_details.all() ],
                                    "rec_time": last_record_obj_by_role.qc_check.formatted_received_at(),
                                    "check_time": last_record_obj_by_role.qc_check.formatted_check_at(),
                                    "cnName": last_record_obj_by_role.qc_check.account.django_user.cnName if last_record_obj_by_role.qc_check.account else '',
                                    "allow_reset":allow_reset
                                }}
                    else:
                        data={"qcCheck": {
                                    "check_record_obj_pk":last_record_obj.qc_check.pk if last_record_obj.qc_check else '',
                                    "failed": last_record_obj.qc_check.failed,
                                    "remark": last_record_obj.qc_check.remark,
                                    "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in last_record_obj.qc_check.failed_details.all() ],
                                    "rec_time": last_record_obj.qc_check.formatted_received_at(),
                                    "check_time": last_record_obj.qc_check.formatted_check_at(),
                                    "cnName": last_record_obj.qc_check.account.django_user.cnName if last_record_obj.qc_check.account else '',
                                    "allow_reset":allow_reset
                                }}

                else:
                    allow_reset=common.check_qc_record_can_reset(last_record_obj_by_role.qc_check)
                    data={"qcCheck": {
                                "check_record_obj_pk":last_record_obj_by_role.qc_check.pk if last_record_obj_by_role.qc_check else '',
                                "failed": last_record_obj_by_role.qc_check.failed,
                                "remark": last_record_obj_by_role.qc_check.remark,
                                "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in last_record_obj_by_role.qc_check.failed_details.all() ],
                                "rec_time": last_record_obj_by_role.qc_check.formatted_received_at(),
                                "check_time": last_record_obj_by_role.qc_check.formatted_check_at(),
                                "cnName": last_record_obj_by_role.qc_check.account.django_user.cnName if last_record_obj_by_role.qc_check.account else '',
                                "allow_reset":allow_reset
                            }}
            else:
                allow_reset=False
                data={"qcCheck": {
                            "check_record_obj_pk":None,
                            "failed": None,
                            "remark": None,
                            "fail_detail":[ ],
                            "rec_time": None,
                            "check_time": None,
                            "cnName": None,
                            "allow_reset":allow_reset
                        }}

   
        elif user_account_obj.role.name=="Teamleader":
            if last_record_obj_by_role.leader_check:
                allow_reset=common.check_qc_record_can_reset(last_record_obj_by_role.leader_check)
                data={"leaderCheck": {
                        "check_record_obj_pk":last_record_obj_by_role.leader_check.pk if last_record_obj_by_role.leader_check else '',
                        "failed": last_record_obj_by_role.leader_check.failed,
                        "remark": last_record_obj_by_role.leader_check.remark,
                        "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in last_record_obj_by_role.leader_check.failed_details.all() ],
                        "rec_time": last_record_obj_by_role.leader_check.formatted_received_at(),
                        "check_time": last_record_obj_by_role.leader_check.formatted_check_at(),
                        "cnName": last_record_obj_by_role.leader_check.account.django_user.cnName if last_record_obj_by_role.leader_check.account else '',
                        "allow_reset":allow_reset
                    }}
            else:
                allow_reset=False
                data={"leaderCheck": {
                            "check_record_obj_pk":None,
                            "failed": None,
                            "remark": None,
                            "fail_detail":[ ],
                            "rec_time": None,
                            "check_time": None,
                            "cnName": None,
                            "allow_reset":allow_reset
                        }}

        elif user_account_obj.role.name=="StoneQC":
            if last_record_obj_by_role.stone_check:
                allow_reset=common.check_qc_record_can_reset(last_record_obj_by_role.stone_check)
                data={"stoneCheck": {
                            "check_record_obj_pk":last_record_obj_by_role.stone_check.pk if last_record_obj_by_role.stone_check else '',
                            "failed": last_record_obj_by_role.stone_check.failed,
                            "remark": last_record_obj_by_role.stone_check.remark,
                            "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in last_record_obj_by_role.stone_check.failed_details.all() ],
                            "rec_time": last_record_obj_by_role.stone_check.formatted_received_at(),
                            "check_time": last_record_obj_by_role.stone_check.formatted_check_at(),
                            "cnName": last_record_obj_by_role.stone_check.account.django_user.cnName if last_record_obj_by_role.stone_check.account else '',
                            "allow_reset":allow_reset
                        }
                    }
            else:
                allow_reset=False
                data={"stoneCheck": {
                            "check_record_obj_pk":None,
                            "failed": None,
                            "remark": None,
                            "fail_detail":[ ],
                            "rec_time": None,
                            "check_time": None,
                            "cnName": None,
                            "allow_reset":allow_reset
                        }}

        else:
            logging.info(f"Other roles {user_account_obj.role.name}, no need to check order on hold")

    return data, last_record_obj_by_role, last_record_obj


def parse_orderview_data_bak(detail_obj, user_account_obj):

    data=[]

    order_route_obj=None
    last_order_flow_record_obj=None
    try:
        order_route_obj=detail_obj.orderrouting
    except workorders.Detail.orderrouting.RelatedObjectDoesNotExist:
        logging.info(f"No route for order {detail_obj}")
        return data, last_order_flow_record_obj, order_route_obj
    except Exception as e:
        logging.error(f"Exception to get order routing objects: {e}")
        return data, last_order_flow_record_obj, order_route_obj

    route_detail_objs=order_route_obj.routedetail_set.filter(flow=user_account_obj.department.flow)
    if route_detail_objs.exists():
        route_detail_obj=route_detail_objs.last()
        record_objs=route_detail_obj.record_set.all()

        if record_objs.exists():
            record_obj=record_objs.last()
            if user_account_obj.role.name=="WORKER":
                # check permission
                data = {"worker": {
                            "actionRecord": [{
                                "action": action_record_obj.get_action_display(),
                                "time": action_record_obj.formatted_time()
                            } for action_record_obj in record_obj.worker.workeractionrecord_set.all()],
                            "cnName": record_obj.worker.account.django_user.cnName if record_obj.worker.account else ''
                        }}
                        
            elif user_account_obj.role.name=="QC":
                data = {"qcCheck": {
                            "check_record_obj_pk":record_obj.qc_check.pk if record_obj.qc_check else '',
                            "failed": record_obj.qc_check.failed,
                            "remark": record_obj.qc_check.remark,
                            "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record_obj.qc_check.failed_details.all() ],
                            "rec_time": record_obj.qc_check.formatted_received_at(),
                            "check_time": record_obj.qc_check.formatted_check_at(),
                            "cnName": record_obj.qc_check.account.django_user.cnName if record_obj.qc_check.account else ''
                        }}
                
            elif user_account_obj.role.name=="Teamleader":
                data={"leaderCheck": {
                            "check_record_obj_pk":record_obj.leader_check.pk if record_obj.leader_check else '',
                            "failed": record_obj.leader_check.failed,
                            "remark": record_obj.leader_check.remark,
                            "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record_obj.leader_check.failed_details.all() ],
                            "rec_time": record_obj.leader_check.formatted_received_at(),
                            "check_time": record_obj.leader_check.formatted_check_at(),
                            "cnName": record_obj.leader_check.account.django_user.cnName if record_obj.leader_check.account else ''
                        }}
            elif user_account_obj.role.name=="StoneQC":
                data={"stoneCheck": {
                            "check_record_obj_pk":record_obj.stone_check.pk if record_obj.stone_check else '',
                            "failed": record_obj.stone_check.failed,
                            "remark": record_obj.stone_check.remark,
                            "fail_detail":[ {"fail_reason_id":failed_detail.reason.pk, "failed_reason":failed_detail.reason.reason, "failed_unit":failed_detail.reason.unit, "fail_qty": failed_detail.quantity} for failed_detail in record_obj.stone_check.failed_details.all() ],
                            "rec_time": record_obj.stone_check.formatted_received_at(),
                            "check_time": record_obj.stone_check.formatted_check_at(),
                            "cnName": record_obj.stone_check.account.django_user.cnName if record_obj.stone_check.account else ''
                        }
                    } 
            else:
                logging.info(f"Other roles {user_account_obj.role.name}, no need to check order on hold")

        last_order_flow_record_obj=common.get_latest_order_flow_record_by_role(detail_obj, user_account_obj)
        # print(last_order_flow_record_obj)

    return data, order_route_obj

def filter_detail_obj_by_check_record(check_record_obj):

    if check_record_obj.check_type==1:
        detail_obj=check_record_obj.qc_check.last().route_detail.order_route.workorder
    elif check_record_obj.check_type==2:
        detail_obj=check_record_obj.leader_check.last().route_detail.order_route.workorder
    elif check_record_obj.check_type==3:
        detail_obj=check_record_obj.stone_check.last().route_detail.order_route.workorder
    else:
        logging.warn(f"No check type match: {check_record_obj.check_type}")
        detail_obj=None

    return detail_obj


def delete_new_created_record(check_record_obj):
    record_obj=get_record_oby_by_qc_record_type(check_record_obj)
    if record_obj:
        seq=record_obj.route_detail.seq

        # check any new record for current flow and next step and with larger pk than self
        record_objs=order_routing.Record.objects.filter(route_detail=record_obj.route_detail, pk__gt=record_obj.pk)
        logging.info(f"Record with current flow {record_obj.route_detail.flow} will be deleted: {record_objs}")

        for obj in record_objs:
            if obj.worker.account:
                logging.error(f"Record is not empty, do not delete: {obj}")
            else:
                logging.info(f"Delete record: {obj}")
                worker_obj=obj.worker
                qc_check_obj=obj.qc_check
                leader_check_obj=obj.leader_check
                stone_check_obj=obj.stone_check
                obj.delete()
                if worker_obj:
                    worker_obj.delete()
                if qc_check_obj:
                    qc_check_obj.delete()
                if leader_check_obj:
                    leader_check_obj.delete()
                if stone_check_obj:
                    stone_check_obj.delete()

        next_flow_route_detail_objs=order_routing.RouteDetail.objects.filter(order_route=record_obj.route_detail.order_route, seq=seq+1)
        next_flow_record_objs=order_routing.Record.objects.filter(route_detail__in=next_flow_route_detail_objs, pk__gt=record_obj.pk)
        logging.info(f"Record with next flow will be deleted: {next_flow_record_objs}")
        
        for obj in next_flow_record_objs:
            if obj.worker.account:
                logging.error(f"Record with next flow is not empty, do not delete: {obj}")
            else:
                logging.info(f"Delete record: {obj}")
                worker_obj=obj.worker
                qc_check_obj=obj.qc_check
                leader_check_obj=obj.leader_check
                stone_check_obj=obj.stone_check
                obj.delete()
                if worker_obj:
                    worker_obj.delete()
                if qc_check_obj:
                    qc_check_obj.delete()
                if leader_check_obj:
                    leader_check_obj.delete()
                if stone_check_obj:
                    stone_check_obj.delete()

def get_record_oby_by_qc_record_type(check_record_obj):
    if check_record_obj.check_type==1:
        record_obj=check_record_obj.qc_check.last()

    elif check_record_obj.check_type==2:
        record_obj=check_record_obj.leader_check.last()
        
    elif check_record_obj.check_type==3:
        record_obj=check_record_obj.stone_check.last()
    else:
        logging.warn(f"No check type {check_record_obj}")
        record_obj=None

    return record_obj
